﻿using System;
using System.IO;
using System.Text;
using System.Windows.Forms;
using Editor.Elements;
using Editor.Utilities;
using Editor.QuestionInterface;

namespace Editor
{
    public partial class ProjectExplorer : Form
    {
        public ProjectExplorer()
        {
            InitializeComponent();
        }

        #region Variable Properties

        private int insertingIndex { get; set; }
        
        private bool isInserting { get; set; }

        private string insertingSubtopicName { get; set; }

        #endregion

        #region Referencing Properties

        public TreeNode SelectedNode
        {
            get { return treeViewExplorer.SelectedNode; }
            set { treeViewExplorer.SelectedNode = value; }
        }

        public TreeNodeCollection TreeNodes
        {
            get { return treeViewExplorer.Nodes; }
        }

        #endregion

        #region Element Handling Methods

        public void RefreshTree()
        {
            LoadProjectToExplorer(EditorForm.CurrentProject);
            ExplorerExpandAll();
        }

        private Element addDepartment(SDictionary<string> deptDict)
        {
            if (EditorForm.CurrentProject == null)
                return null;

            Department newDepartment = EditorForm.CurrentProject.AddChildElement(deptDict)
                as Department;
            TreeNode elementNode = new TreeNode(deptDict[EditorForm.CurrentLanguage]);

            elementNode.Tag = newDepartment;
            EditorForm.TreeNodes.Add(elementNode);
            EditorForm.ExplorerExpandAll();

            return newDepartment;
        }

        private void addElement(string title)
        {
            Element newElement = addElementDialog(title);

            if (newElement != null)
            {
                EditorForm.IsSaved = false;
            }
        }

        private Element addElementDialog(string title)
        {
            CreateForm cf = new CreateForm(title);
            TreeNode selectedNode = EditorForm.SelectedNode;

            if (cf.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                EditorForm.SelectedNode = selectedNode;

                return addElementToSelectedNode(cf.Dictionary);
            }

            return null;
        }

        private bool addElement(TreeNode parentNode, Element child)
        {
            TreeNode treeNode = new TreeNode(child.CurrentName);

            if (parentNode.Nodes.Contains(treeNode))
            {
                return false;
            }
            else
            {
                Element parentElement = parentNode.Tag as Element;
                parentElement.ChildElements.Add(child);
                treeNode.Tag = child;
                parentNode.Nodes.Add(treeNode);
                return true;
            }
        }

        private Element addElementToSelectedNode(SDictionary<string> dict)
        {
            if (SelectedNode == null)
                return addDepartment(dict);

            Element parent, child;

            parent = SelectedNode.Tag as Element;
            child = parent.AddChildElement(dict);

            TreeNode elementNode = new TreeNode(dict[EditorForm.CurrentLanguage]);

            elementNode.Tag = child;
            SelectedNode.Nodes.Add(elementNode);
            EditorForm.ExplorerExpandAll();

            return child;
        }

        public void ExplorerExpandAll()
        {
            treeViewExplorer.ExpandAll();
        }

        private TreeNode getNodeOfElement(Element element)
        {
            string[] path = element.Path.Split(new char[] { Path.DirectorySeparatorChar },
                StringSplitOptions.RemoveEmptyEntries);
            TreeNode currentNode = getTreeNodeByName(TreeNodes, path[1]);

            for (int i = 2; i < path.Length; ++i)
                currentNode = getTreeNodeByName(currentNode.Nodes, path[i]);

            return currentNode;
        }

        private TreeNode getTreeNodeByName(TreeNodeCollection nodes, string name)
        {
            foreach (TreeNode node in nodes)
                if (node.Text.Equals(name))
                    return node;
            return null;
        }

        private void loadElementToExplorer(Element element, TreeNodeCollection nodes)
        {
            TreeNode parentNode = new TreeNode(element.Dictionary[EditorForm.CurrentLanguage]);

            foreach (Element child in element.ChildElements)
                loadElementToExplorer(child, parentNode.Nodes);

            parentNode.Tag = element;
            nodes.Add(parentNode);
        }

        public void LoadProjectToExplorer(Project project)
        {
            TreeNodes.Clear();
            foreach (Department dept in project.ChildElements)
                loadElementToExplorer(dept, TreeNodes);
        }

        public void UpdateNodes()
        {
            foreach (TreeNode node in treeViewExplorer.Nodes)
                node.Text = (node.Tag as Element).Dictionary[EditorForm.CurrentLanguage];
        }

        #endregion

        #region Event Handling Methods

        private void addElement_Click(object sender, EventArgs e)
        {
            if (SelectedNode == null)
                addElement("Mühendislik Ekle");
            else if (SelectedNode.Tag is Department)
                addElement("Ders Ekle");
            else if (SelectedNode.Tag is Course)
                addElement("Konu Ekle");
            else if (SelectedNode.Tag is Topic)
                addElement("Alt Konu Ekle");
            else if (SelectedNode.Tag is Subtopic)
                addElement("Sayfa Ekle");

            EditorForm.IsSaved = false;
        }

        private void deleteElement_Click(object sender, EventArgs e)
        {
            Element selectedElement = SelectedNode.Tag as Element;
            selectedElement.Remove();
            SelectedNode.Remove();
            
            EditorForm.PageProperties = false;
        }

        private void editElement_Click(object sender, EventArgs e)
        {
            SelectedNode.BeginEdit();
        }

        private void ProjectExplorer_FormClosed(object sender, FormClosedEventArgs e)
        {
            EditorForm.ProjectExplorerChecked = false;
        }

        private void relocatePage_Click(object sender, EventArgs e)
        {
            isInserting = true;
            insertingIndex = SelectedNode.Index;
            insertingSubtopicName = (SelectedNode.Parent.Tag as Subtopic).
                Dictionary[EditorForm.CurrentLanguage];
            //treeViewExplorer_AfterSelect will take care of inserting mode
        }

        private void treeViewExplorer_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
        {
            if (e.Label != null)
            {
                Element selectedElement = EditorForm.SelectedNode.Tag as Element;
                string oldPath = selectedElement.Path;
                selectedElement.Dictionary[EditorForm.CurrentLanguage] = e.Label;
                EditorForm.IsSaved = false;
            }
        }

        private void treeViewExplorer_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (isInserting)
            {
                Subtopic parentSubtopic = (SelectedNode.Parent.Tag as Subtopic);

                if (parentSubtopic.CurrentName.Equals(insertingSubtopicName))
                {
                    TreeNodeCollection subtopicCollection = SelectedNode.Parent.Nodes;
                    TreeNode insertingNode = subtopicCollection[insertingIndex];
                    
                    if (insertingNode.Tag is Page)
                    {
                        int selectedIndex = SelectedNode.Index;

                        parentSubtopic.ChildElements.RemoveAt(insertingIndex);
                        parentSubtopic.ChildElements.Insert(selectedIndex, insertingNode.Tag);
                        subtopicCollection.RemoveAt(insertingIndex);
                        subtopicCollection.Insert(selectedIndex, insertingNode);
                        EditorForm.IsSaved = false;
                    }
                }
                 
                isInserting = false;
            }
            else if (e.Node.Tag is Page && (EditorForm.CurrentPage == null ||
                !EditorForm.CurrentPage.Equals(e.Node.Tag as Page)))
            {
                 EditorForm.SwitchToSelectedPage();
            }
        }

        private void treeViewExplorer_KeyUp(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Space:
                    SelectedNode.BeginEdit();
                    break;
            }
        }

        private void treeViewExplorer_MouseUp(object sender, MouseEventArgs e)
        {
            // Select the clicked node
            treeViewExplorer.SelectedNode = treeViewExplorer.GetNodeAt(e.X, e.Y);

            if (e.Button == MouseButtons.Right)
            {
                if (treeViewExplorer.SelectedNode == null)
                    contextMenuStripDept.Show(treeViewExplorer, e.Location);
                else if (treeViewExplorer.SelectedNode.Tag is Page)
                    contextMenuStripPage.Show(treeViewExplorer, e.Location);
                else if (treeViewExplorer.SelectedNode.Tag is Subtopic)
                    contextMenuStripSubtopic.Show(treeViewExplorer, e.Location);
                else
                    contextMenuStripOther.Show(treeViewExplorer, e.Location);
            }
        }

        private void copyPage_Click(object sender, EventArgs e)
        {
            CreateForm cf = new CreateForm("Kopya Sayfa Ekle");

            if (cf.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                Page selectedPage = SelectedNode.Tag as Page;
                Page copyPage = selectedPage.Clone() as Page;

                copyPage.Dictionary = cf.Dictionary.Clone() as SDictionary<string>;

                if (!addElement(SelectedNode.Parent, copyPage))
                    MessageBox.Show(cf.Dictionary[EditorForm.DefaultLanguage] + " sayfası zaten var!", 
                        "Hata!", MessageBoxButtons.OK, MessageBoxIcon.Error);

                EditorForm.IsSaved = false;
            }
        }

        #endregion

        private void toolStripMenuItemInteractivePage_Click(object sender, EventArgs e)
        {
            ///<title>Next plan</title>
            ///Show create new interactive page dialog to get it filled with info
            ///and get created data from the object and use it as a page!!!
            ///That means, it should be possible to perform all kinds of tasks 
            ///on the new kind of page like the previous one!!!
            ///Either redefine it or find a way to generilize it! There is a tradeoff!
            

            ///It does not make any sense to copy or make template of an interactive page
            ///So it's not a simple page! Maybe it is not needed to inherit it form the Page!
            ///First of all it has many differences like it has no PageControls as children
            ///Neither it is a simple Element class!
            
            ///Maybe instead of making custom pages, like with positions etc. there should be
            ///types of pages like content, question, interactive question etc. and they should
            ///be redesigned in every system instead of one simple design!?
            

            ///Is it ok to constrain user to design pages? Isn't editor all about editing??
            ///But inserting just texts and pictures will reduce the complexity of the database!!
            ///Using formatted data will make database contain more information about style
            ///On the other hand, use can well define some pages with designer format to reuse 
            ///instead of hard-coded hard-to-change inflexible forms
            
            ///The thing here is: Do we really need custom pages? Unless it is not "that" important
            ///it will reduce the cost of database design!!!
            ///Also, we are highly depending on current screen size with custom pages. But,
            ///if we do it programmatically we can change it only in codes and all the pages
            ///(maybe there will be thousands or even millions (!) of pages) will be changed
            ///automatically!
            
            ///For the demo, it is unlikely that we can use this model. But still it will be the plan
            ///just after it!
            
            ///By the way, redefining own systems is bogus. It's a pain in the *** to redefine important
            ///components which are already very-well defined.
            ///Here reducing the dependency will be a very brilliant idea. So it will not be required to
            ///make changes on previously created pages.
            
            ///In the next type there will be templates to choose rather than adding page, question page
            ///MenuStrip!

            AddInteractivePageForm addInteractivePageForm = new AddInteractivePageForm();

            if (addInteractivePageForm.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                SDictionary<string> dictionary = new SDictionary<string>();


                foreach (string language in EditorForm.SupportedLanguages)
                    dictionary[language] = addInteractivePageForm.QuestionName;

                Page page = new Page(dictionary);

                page.AddPageControl(addInteractivePageForm.InteractivePage);

                addElement(treeViewExplorer.SelectedNode, page);
            }
        }
    }
}
